
#include <BKeyEvent>
#include <BCharEvent>
#include <BEvent>
#include <BEvent>
#include <BFocusEvent>
#include <BMouseEvent>
#include <BChangeEvent>
#include <BEvent>
#include <BFile>
#include <BOpenGL>
#include <BPainter>
#include <BFont>
#include <BCursor>
#include <BGroupBox>
#include <BWidget>

#include "IGlobal.h"
#include "IWindow.h"
#include "member_BWidget.h"
#include "member_BLayout.h"
#include "member_BAnimation.h"
#include "member_BDrag.h"
#include "member_BStyle.h"

using namespace BWE;

#define member						(*(member_BWidget*)_ptr)
#define member_allocate()			_ptr = new member_BWidget(this)
#define member_release()			delete (member_BWidget*)_ptr

extern BStyleHolder		app_style;

BWidget::BWidget(BWidget* parent)
{
	member_allocate();
	setParent(parent);
}
BWidget::BWidget(const BString& name, BWidget* parent)
{
	member_allocate();
	setName(name);
	setParent(parent);
}
BWidget::~BWidget()
{
	App_DetachWindow(member.window);
	member_release();
}

void BWidget::setTitle(const BString& title)
{
	if (member.title != title)
	{
		member.title = title;
		emit(Signal_TitleChanged, title);

		BChangeEvent change(Change_Title);
		member.procEvent(change);
	}
}
const BString& BWidget::title() const
{
	return member.title;
}

void BWidget::setTips(const BString& tips)
{
	if (member.tips != tips)
	{
		member.tips = tips;
		BChangeEvent changeEvent;
		changeEvent.setTips(tips);
		member.procEvent(changeEvent);
		emit(Signal_TipsChanged, member.tips);
	}
}
const BString& BWidget::tips() const
{
	return member.tips;
}

void BWidget::show()
{
	if (!member.parent)
	{
		if (!member.window)
		{
			App_AttachWindow(this);
		}
		member.window->showNormal();
	}
	setVisible(true);
}
void BWidget::popup()
{
	this->setVisible(true);
	BWidget* root = this->root();
	if (root != this && widget_member(root)->window)
	{
		widget_member(root)->window->popup(this, true);
		BEvent event(Event_Popup, false);
		this->event(event);
	}
}
void BWidget::hide()
{
	this->setVisible(false);
	if (member.window)
	{
		member.window->hideWindow();
		member.window->popup(this, false);
		BEvent event(Event_Popup, false);
		this->event(event);
	}
}
void BWidget::raise()
{
	if(member.parent && order() > 0)
	{
		BList<BWidgetHolder>& widgetlist = ((member_BWidget*)member.parent->_ptr)->children;
		BHolder<BWidget> holder = this;
		widgetlist.remove(this);
		widgetlist.insert(0, this);
		member.parent->fresh();
	}
}
void BWidget::lower()
{
	if(member.parent)
	{
		BList<BWidgetHolder>& widgetlist = ((member_BWidget*)member.parent->_ptr)->children;
		BHolder<BWidget> holder = this;
		widgetlist.remove(this);
		widgetlist.append(this);
		member.parent->fresh();
	}
}
void BWidget::fresh()
{
	member.refresh = true;
}

void BWidget::setOrder(int order)
{
	if(member.parent)
	{
		BList<BWidgetHolder>& widgetlist = widget_member(member.parent)->children;
		int pos = widgetlist.indexOf(this);
		widgetlist.move(pos, order);
		this->fresh();
	}
}
int BWidget::order() const
{
	if(member.parent)
	{
		BList<BWidgetHolder>& widgetlist = widget_member(member.parent)->children;
		return widgetlist.indexOf(this);
	}
	return -1;
}

void BWidget::setFocus(bool focus)
{
	if (member.focus != focus)
	{
		member.focus = true;
		BWidget* root = this->root();
		if (root && widget_member(root)->window)
		{
			if(focus)
				widget_member(root)->window->focus(this);
			else
				widget_member(root)->window->focus(0);
		}
		fresh();
	}
}
bool BWidget::focus() const
{
	return member.focus;
}

void BWidget::setFloating(bool floating)
{
	if (member.floating != floating)
	{
		member.floating = floating;
		fresh();
	}
}
bool BWidget::floating() const
{
	return member.floating;
}

void BWidget::setDroppable(bool droppable)
{
	if (member.droppable != droppable)
	{
		member.droppable = droppable;
	}
}
bool BWidget::droppable() const
{
	return member.droppable;
}

void BWidget::setPos(const BPoint& pos)
{
	if(member.pos != pos)
	{
		member.pos = pos;
		BEvent moveEvent(Event_Move);
		member.procEvent(moveEvent);
		emit(Signal_Moved, member.pos);
		BWidget* root = this->root();
		if (root != this && widget_member(root)->window)
		{
			widget_member(root)->window->refresh = true;
		}
		if (member.window)
		{
			member.window->setWindowPos(member.pos);
		}

	}
}
void BWidget::setPos(int x, int y)
{
	setPos(BPoint(x, y));
}
const BPoint& BWidget::pos() const
{
	return member.pos;
}

void BWidget::move(const BPoint& offset)
{
	setPos(member.pos + offset);
}
void BWidget::move(int x, int y)
{
	setPos(member.pos + BPoint(x, y));
}

void BWidget::setSize(const BSize& size)
{
	BSize temp = size;
	temp.limit(member.minSize, member.maxSize);
	if (member.sizePolicy.widthPolicy() == Policy_Fixed)
		temp.width() = member.size.width();
	if (member.sizePolicy.heightPolicy() == Policy_Fixed)
		temp.height() = member.size.height();
	if (member.size != temp)
	{
		member.size = temp;
		member.dirtyRect = true;
		member.fbo_resized = true;

		member.dirtyLayouts(false);

		BEvent resizeEvent(Event_Resize);
		member.procEvent(resizeEvent);
		emit(Signal_Resize, member.size);
		fresh();

		if (member.window)
		{
			member.window->setWindowSize(member.size);
		}
	}
}
void BWidget::setSize(int width, int height)
{
	setSize(BSize(width, height));
}
const BSize& BWidget::size() const
{
	return member.size;
}
BSize BWidget::shellSize() const
{
	int b = member.border;
	const BPerchs& p = member.perchs;
	const BMargins& m = member.margins;
	int swidth = b + p.left() + m.left() + m.right() + p.right() + b;
	int sheight = b + p.top() + m.top() + m.bottom() + p.bottom() + b;
	return BSize(swidth, sheight);
}

void BWidget::setWidth(int width)
{
	int height = member.size.height();
	setSize(BSize(width, height));
}
int BWidget::width() const
{
	return member.size.width();
}

void BWidget::setHeight(int height)
{
	int width = member.size.width();
	BSize size(width, height);
	setSize(size);
}
int BWidget::height() const
{
	return member.size.height();
}

void BWidget::setAbsolutePos(const BPoint& absolutePos)
{
	BPoint pos = absolutePos - this->absolutePos();
	setPos(pos);
}
void BWidget::setAbsolutePos(int absoluteX, int absoluteY)
{
	BPoint abPos(absoluteX, absoluteY);
	setAbsolutePos(abPos);
}
BPoint BWidget::absolutePos() const
{
	BPoint abPos = globalPos() - root()->pos();
	return abPos;
}

void BWidget::setGlobalPos(const BPoint& globalPos)
{

}
void BWidget::setGlobalPos(int globalX, int globalY)
{
	setGlobalPos(BPoint(globalX, globalY));
}
BPoint BWidget::globalPos() const
{
	BPoint glPos = member.pos;
	const BWidget* widget = this;
	while(widget->parent())
	{
		widget = widget->parent();
		glPos += widget->pos();
	}
	return glPos;
}

void BWidget::setRect(const BRect& rect)
{
	BPoint pos = rect.pos();
	setPos(pos);
	BSize size = rect.size();
	setSize(size);
}
void BWidget::setRect(int x, int y, int width, int height)
{
	setPos(BPoint(x, y));
	setSize(BSize(width, height));
}
BRect BWidget::rect() const
{
	return BRect(member.pos, member.size);
}
BRect BWidget::rect(Part part) const
{
	member.adjustRects();

	switch (part)
	{
	case Part_Client:
		return member.rectClient;
	case Part_Top:
		return member.rectTop;
	case Part_Left:
		return member.rectLeft;
	case Part_Right:
		return member.rectRight;
	case Part_Bottom:
		return member.rectBottom;
	case Part_Title:
		return member.rectTitle;
	default:
		return BRect(member.pos, member.size);
	}
}

void BWidget::setAbsoluteRect(const BRect& absoluteRect)
{
	BPoint localPoint;
	if (member.parent)
	{
		localPoint = member.parent->absolutePos();
	}
	BPoint pos = absoluteRect.pos() - localPoint;
	BSize size = absoluteRect.size();
	setPos(pos);
	setSize(size);
}
void BWidget::setAbsoluteRect(int x, int y, int width, int height)
{
	BPoint pos = BPoint(x, y) - absolutePos();
	BSize size(width, height);
	setPos(pos);
	setSize(size);
}
BRect BWidget::absoluteRect() const
{
	return BRect(absolutePos(), member.size);
}

void BWidget::setGlobalRect(const BRect& absoluteRect)
{
	BPoint glPos = absoluteRect.pos();
	BSize size = absoluteRect.size();
	setGlobalPos(glPos);
	setSize(size);
}
void BWidget::setGlobalRect(int x, int y, int width, int height)
{
	BPoint glPos(x, y);
	BSize size(width, height);
	setGlobalPos(glPos);
	setSize(size);
}
BRect BWidget::globalRect() const
{
	BPoint glPos = this->globalPos();
	return BRect(glPos, member.size);
}

BPoint BWidget::mapTo(const BWidget* widget, const BPoint& point) const
{
	if (!widget)
		return BPoint();

	BPoint upPoint = point;
	const BWidget* uw = this;
	while (uw)
	{
		if (uw == widget)
			return upPoint;
		upPoint += uw->pos();
		uw = uw->parent();
	}

	BPoint downPoint = point;
	const BWidget* dw = widget;
	while (dw)
	{
		if (dw == this)
			return downPoint;
		downPoint -= dw->pos();
		dw = dw->parent();
	}
	return BPoint();
}
BPoint BWidget::mapFrom(const BWidget* widget, const BPoint& point) const
{
	if (!widget)
		return BPoint();

	BPoint upPoint = point;
	const BWidget* uw = widget;
	while (uw)
	{
		if (uw == this)
			return upPoint;
		upPoint += uw->pos();
		uw = uw->parent();
	}

	BPoint downPoint = point;
	const BWidget* dw = this;
	while (dw)
	{
		if (dw == widget)
			return downPoint;
		downPoint -= dw->pos();
		dw = dw->parent();
	}
	return BPoint();
}

BRect BWidget::mapTo(const BWidget* widget, const BRect& rect) const
{
	if (!widget)
		return BRect();

	BRect upRect = rect;
	const BWidget* uw = this;
	while (uw)
	{
		if (uw == widget)
			return upRect;
		upRect += uw->pos();
		uw = uw->parent();
	}

	BRect downRect = rect;
	const BWidget* dw = widget;
	while (dw)
	{
		if (dw == this)
			return downRect;
		downRect -= dw->pos();
		dw = dw->parent();
	}
	return BRect();
}
BRect BWidget::mapFrom(const BWidget* widget, const BRect& rect) const
{
	if (!widget)
		return BRect();

	BRect upRect = rect;
	const BWidget* uw = widget;
	while (uw)
	{
		if (uw == this)
			return upRect;
		upRect += uw->pos();
		uw = uw->parent();
	}

	BRect downRect = rect;
	const BWidget* dw = this;
	while (dw)
	{
		if (dw == widget)
			return downRect;
		downRect -= dw->pos();
		dw = dw->parent();
	}
	return BRect();
}

void BWidget::setMinSize(const BSize& minSize)
{
	if(member.minSize != minSize)
	{
		member.minSize = minSize;
		BSize size = member.size;
		size.limit(member.minSize, member.maxSize);
		this->setSize(size);
	}
}
void BWidget::setMinSize(int minWidth, int minHeight)
{
	setMinSize(BSize(minWidth, minHeight));
}
const BSize& BWidget::minSize() const
{
	return member.minSize;
}

void BWidget::setMaxSize(const BSize& maxSize)
{
	if(member.maxSize != maxSize)
	{
		member.maxSize = maxSize;
		BSize size = member.size;
		size.limit(member.minSize, member.maxSize);
		this->setSize(size);
	}
}
void BWidget::setMaxSize(int maxWidth, int maxHeight)
{
	setMaxSize(BSize(maxWidth, maxHeight));
}
const BSize& BWidget::maxSize() const
{
	return member.maxSize;
}

void BWidget::setFixedWidth(int fixedWidth)
{
	setWidth(fixedWidth);
	setWidthPolicy(Policy_Fixed);
}
void BWidget::setFixedHeight(int fixedHeight)
{
	setHeight(fixedHeight);
	setHeightPolicy(Policy_Fixed);
}
void BWidget::setFixedSize(const BSize& fixedSize)
{
	setSize(fixedSize);
	setSizePolicy(BSizePolicy(Policy_Fixed, Policy_Fixed));
}
void BWidget::setFixedSize(int fixedWidth, int fixedHeight)
{
	setSize(fixedWidth, fixedHeight);
	setSizePolicy(BSizePolicy(Policy_Fixed, Policy_Fixed));
}

void BWidget::setWidthStretch(float widthStretch)
{
	BSizeStretch sizeStretch(widthStretch, member.sizeStretch.heightStretch());
	setSizeStretch(sizeStretch);
}
float BWidget::widthStretch() const
{
	return member.sizeStretch.widthStretch();
}

void BWidget::setHeightStretch(float heightStretch)
{
	BSizeStretch sizeStretch(member.sizeStretch.widthStretch(), heightStretch);
	setSizeStretch(sizeStretch);
}
float BWidget::heightStretch() const
{
	return member.sizeStretch.heightStretch();
}

void BWidget::setSizeStretch(float widthStretch, float heightStretch)
{
	setSizeStretch(BSizeStretch(widthStretch, heightStretch));
}
void BWidget::setSizeStretch(const BSizeStretch& sizeStretch)
{
	if(member.sizeStretch != sizeStretch)
	{
		member.sizeStretch = sizeStretch;
		member.dirtyLayouts();
	}
}
const BSizeStretch& BWidget::sizeStretch() const
{
	return member.sizeStretch;
}

void BWidget::setWidthPolicy(Policy widthPolicy)
{
	BSizePolicy sizePolicy(widthPolicy, member.sizePolicy.heightPolicy());
	setSizePolicy(sizePolicy);
}
Policy BWidget::widthPolicy() const
{
	return member.sizePolicy.widthPolicy();
}

void BWidget::setHeightPolicy(Policy heightPolicy)
{
	BSizePolicy sizePolicy(member.sizePolicy.widthPolicy(), heightPolicy);
	setSizePolicy(sizePolicy);
}
Policy BWidget::heightPolicy() const
{
	return member.sizePolicy.heightPolicy();
}

void BWidget::setSizePolicy(Policy widthPolicy, Policy heightPolicy)
{
	setSizePolicy(BSizePolicy(widthPolicy, heightPolicy));
}
void BWidget::setSizePolicy(const BSizePolicy& sizePolicy)
{
	if(member.sizePolicy != sizePolicy)
	{
		member.sizePolicy = sizePolicy;
		member.dirtyLayouts();
	}
}
const BSizePolicy& BWidget::sizePolicy() const
{
	return member.sizePolicy;
}

const BSize& BWidget::clientSize() const
{
	member.adjustRects();
	return member.rectClient.size();
}
const BRect& BWidget::clientRect() const
{
	member.adjustRects();
	return member.rectClient;
}

void BWidget::setClientSize(const BSize& clientSize)
{
	setClientSize(clientSize.width(), clientSize.height());
}
void BWidget::setClientSize(int contentWidth, int contentHeight)
{
	int b = member.border;
	const BPerchs& p = member.perchs;
	const BMargins& m = member.margins;

	int width = b + p.left() + m.left() + contentWidth + m.right() + p.right() + b;
	int height = b + p.top() + m.top() + contentHeight + m.bottom() + p.bottom() + b;

	this->setSize(width, height);
}

void BWidget::setBorder(int border)
{
	if(member.border != border)
	{
		member.border = border;
		member.dirtyRect = true;
		BChangeEvent changeEvent;
		changeEvent.setBorder(member.border);
		member.procEvent(changeEvent);
		member.dirtyLayouts();
		fresh();
	}
}
int BWidget::border() const
{
	return member.border;
}

void BWidget::setPerchs(const BPerchs& perchs)
{
	if (member.perchs != perchs)
	{
		member.perchs = perchs;
		member.dirtyRect = true;
		BChangeEvent changeEvent;
		changeEvent.setPerchs(perchs);
		member.procEvent(changeEvent);
		member.dirtyLayouts();
		fresh();
	}
}
void BWidget::setPerchs(int left, int top, int right, int bottom)
{
	setPerchs(BPerchs(left, top, right, bottom));
}
const BPerchs& BWidget::perchs() const
{
	return member.perchs;
}

void BWidget::setPerch(Part part, int value)
{
	BPerchs perchs = member.perchs;
	switch (part)
	{
	case Part_Left:
		perchs.left() = value;
		break;
	case Part_Top:
		perchs.top() = value;
		break;
	case Part_Right:
		perchs.right() = value;
		break;
	case Part_Bottom:
		perchs.bottom() = value;
		break;
	default:
		break;
	}
	this->setPerchs(perchs);
}
int BWidget::perch(Part part) const
{
	switch (part)
	{
	case Part_Left:
		return member.perchs.left();
	case Part_Top:
		return member.perchs.top();
	case Part_Right:
		return member.perchs.right();
	case Part_Bottom:
		return member.perchs.bottom();
	default:
		return -1;
	}
}

void BWidget::setMargins(const BMargins& margins)
{
	if(member.margins != margins)
	{
		member.margins = margins;
		member.dirtyRect = true;
		BChangeEvent changeEvent;
		changeEvent.setMargins(margins);
		member.procEvent(changeEvent);
		member.dirtyLayouts();
		fresh();
	}
}
void BWidget::setMargins(int left, int top, int right, int bottom)
{
	BMargins margins(left, top, right, bottom);
	setMargins(margins);
}
const BMargins& BWidget::margins() const
{
	return member.margins;
}

void BWidget::setMargin(Part part, int value)
{
	BMargins margins = member.margins;
	switch (part)
	{
	case Part_Left:
		margins.left() = value;
		break;
	case Part_Top:
		margins.top() = value;
		break;
	case Part_Right:
		margins.right() = value;
		break;
	case Part_Bottom:
		margins.bottom() = value;
		break;
	default:
		return;
	}
	this->setMargins(margins);
}
int BWidget::margin(Part part) const
{
	switch (part)
	{
	case Part_Left:
		return member.margins.left();
	case Part_Top:
		return member.margins.top();
	case Part_Right:
		return member.margins.right();
	case Part_Bottom:
		return member.margins.bottom();
	default:
		return -1;
	}
}

void BWidget::setVisible(bool visible)
{
	if(member.visible != visible)
	{
		member.visible = visible;
		if(member.visible)
		{
			BEvent event(Event_Show);
			member.procEvent(event);
			emit(Signal_Show);
		}
		else
		{
			BWidget* root = this->root();
			if (root && root != this && widget_member(root)->window)
			{
				widget_member(root)->window->popup(this, false);
			}
			BEvent event(Event_Hide);
			member.procEvent(event);
			emit(Signal_Hide);
		}
		member.dirtyLayouts();
		this->fresh();
	}
}
bool BWidget::visible() const
{
	return member.visible;
}

void BWidget::setModal(bool modal)
{
	if (member.modal != modal)
	{
		member.modal = modal;
		BChangeEvent changeEvent;
		changeEvent.setModal(modal);
		member.procEvent(changeEvent);
	}
}
bool BWidget::modal() const
{
	return member.modal;
}

void BWidget::setCursor(CursorType cursorType)
{
	if (member.cursor)
	{
		member.cursor->setType(cursorType);
	}
	else
	{
		BCursor* cursor = new BCursor(cursorType);
		setCursor(cursor);
	}
}
void BWidget::setCursor(BCursor* cursor)
{
	if (member.cursor != cursor)
	{
		member.cursor = cursor;
		BChangeEvent changeEvent;
		changeEvent.setCursor(cursor);
		this->event(changeEvent);
	}
}
BCursor* BWidget::cursor()
{
	return member.cursor.ptr();
}
const BCursor* BWidget::cursor() const
{
	return member.cursor.ptr();
}
const BCursor* BWidget::realCursor() const
{
	const BWidget* widget = this;
	while(widget)
	{
		const BCursor* cursor = widget->cursor();
		if(cursor)
			return cursor;
		widget = widget->parent();
	}
	return 0;
}

void BWidget::setFont(BFont* font)
{
	if (!member.style)
		member.style = new BStyle();
	member.style->setFont(font);
	member.freshStyleTree(this);
}
void BWidget::setFont(const BString& family, const BSize& size)
{
	BFont* font = new BFont(family, size);
	setFont(font);
}
const BFont* BWidget::font() const
{
	if (member.style)
		return member.style->font();
	BStyle* style = member.lowerStyle();
	if (style)
		return style->font();
	return 0;
}

void BWidget::setStyle(BStyle* style)
{
	if (style == this->realStyle())
		style = 0;
	if (member.style != style)
	{
		if (member.style)
			style_member(member.style)->lower = 0;
		member.style = style;
		member.freshStyleTree(this);
	}
}
BStyle* BWidget::style() const
{
	return member.style;
}
BStyle* BWidget::realStyle() const
{
	if (member.style)
		return member.style;
	return member.lowerStyle();
}

void BWidget::setStyleSheet(const BString& styleSheet)
{
	if (BFile::Exists(styleSheet))
	{
		BFile file(styleSheet);
		if (file.open(BFile::Mode_Read))
		{
			file.readString(member.styleSheet);
		}
	}
	else
	{
		member.styleSheet = styleSheet;
	}
	if (member.styleSheet.empty())
	{
		member.styleDriver = 0;
	}
	else
	{
		if (!member.styleDriver)
			member.styleDriver = new IStyleDriver();
		member.styleDriver->init(member.styleSheet);
		member.styleDriver->apply(this);
	}
}
const BString& BWidget::styleSheet() const
{
	return member.styleSheet;
}

void BWidget::setLayout(BLayout* layout, Part part)
{
	if (!layout)
		return;

	BHolder<BLayout>* holder = 0;
	switch (part)
	{
	case Part_Title:
		holder = &member.titleLayout;
		break;
	case Part_Client:
		holder = &member.mainLayout;
		break;
	case Part_Top:
		holder = &member.topLayout;
		break;
	case Part_Left:
		holder = &member.leftLayout;
		break;
	case Part_Right:
		holder = &member.rightLayout;
		break;
	case Part_Bottom:
		holder = &member.bottomLayout;
		break;
	default:
		break;
	}
	if (holder)
	{
		if ((*holder) != layout)
		{
			if ((*holder))
				(*holder)->setHost(0);
			(*holder) = layout;
			if ((*holder))
				(*holder)->setHost(this);
			member.dirtyLayouts();
		}
	}
	else
	{
		if (!member.freeLayouts.contain(layout))
		{
			member.freeLayouts.append(layout);
			layout->setHost(this);
		}
	}
	fresh();
}
BLayout* BWidget::layout(Part part)
{
	if (part == Part_Title)
		return member.titleLayout;
	if (part == Part_Client)
		return member.mainLayout;
	if (part == Part_Top)
		return member.topLayout;
	if (part == Part_Left)
		return member.leftLayout;
	if (part == Part_Right)
		return member.rightLayout;
	if (part == Part_Bottom)
		return member.bottomLayout;
	return 0;
}
const BLayout* BWidget::layout(Part part) const
{
	if (part == Part_Client)
		return member.mainLayout;
	if (part == Part_Top)
		return member.topLayout;
	if (part == Part_Left)
		return member.leftLayout;
	if (part == Part_Right)
		return member.rightLayout;
	if (part == Part_Bottom)
		return member.bottomLayout;
	return 0;
}
bool BWidget::removeLayout(BLayout* layout)
{
	BHolder<BLayout>* holder = 0;
	if (member.mainLayout == layout)
		holder = &member.mainLayout;
	if (member.leftLayout == layout)
		holder = &member.leftLayout;
	if (member.rightLayout == layout)
		holder = &member.rightLayout;
	if (member.topLayout == layout)
		holder = &member.topLayout;
	if (member.bottomLayout == layout)
		holder = &member.bottomLayout;

	if (holder == 0)
		return false;

	layout->clear();
	(*holder) = 0;

	return true;
}

void BWidget::setAnimation(BAnimation* animation)
{
	if (member.animation != animation)
	{
		member.animation = animation;
		animation_member(member.animation)->detach();
		animation_member(member.animation)->attach(this);
		BChangeEvent changeEvent;
		changeEvent.setAnimation(animation);
		member.procEvent(changeEvent);
	}
}
BAnimation* BWidget::animation()
{
	return member.animation;
}
const BAnimation* BWidget::animation() const
{
	return member.animation;
}

void BWidget::hintSize(Part part)
{
	BSize csize = this->clientSize();
	if (part & Part_Client && member.mainLayout)
	{
		csize = member.mainLayout->sizeHint();
	}
	if (part & Part_Left && member.leftLayout)
	{
		BSize hsize = member.leftLayout->sizeHint();
		if (this->perch(Part_Left) < hsize.width())
			this->setPerch(Part_Left, hsize.width());
		if (csize.height() < hsize.height())
			csize.height() = hsize.height();
	}
	if (part & Part_Top && member.topLayout)
	{
		BSize hsize = member.topLayout->sizeHint();
		if (this->perch(Part_Top) < hsize.height())
			this->setPerch(Part_Top, hsize.height());
		if (csize.width() < hsize.width())
			csize.width() = hsize.width();
	}
	if (part & Part_Right && member.rightLayout)
	{
		BSize hsize = member.rightLayout->sizeHint();
		if (this->perch(Part_Right) < hsize.width())
			this->setPerch(Part_Right, hsize.width());
		if (csize.height() < hsize.height())
			csize.height() = hsize.height();
	}
	if (part & Part_Bottom && member.bottomLayout)
	{
		BSize hsize = member.bottomLayout->sizeHint();
		if (this->perch(Part_Bottom) < hsize.height())
			this->setPerch(Part_Bottom, hsize.height());
		if (csize.width() < hsize.width())
			csize.width() = hsize.width();
	}
	this->setClientSize(csize);
	member.dirtyLayouts();
}
BSize BWidget::sizeHint() const
{
	int b = member.border;
	const BPerchs& p = member.perchs;
	const BMargins& m = member.margins;
	int hintWidth = b + p.left() + m.left() + m.right() + p.right() + b;
	int hintHeight = b + p.top() + m.top() + m.bottom() + p.bottom() + b;

	if (member.mainLayout && member.mainLayout->able())
	{
		BSize clientSize = member.mainLayout->sizeHint();
		hintWidth += clientSize.width();
		hintHeight += clientSize.height();
	}

	if (member.sizePolicy.widthPolicy() == Policy_Fixed)
		hintWidth = member.size.width();
	if (member.sizePolicy.heightPolicy() == Policy_Fixed)
		hintHeight = member.size.height();

	BSize hintSize(hintWidth, hintHeight);
	hintSize.limit(member.minSize, member.maxSize);
	return hintSize;
}

bool BWidget::catchPoint(const BPoint& point)
{
	return this->rect().contain(point);
}

BWidget* BWidget::root()
{
	BWidget* widget = this;
	while (widget->parent())
		widget = widget->parent();
	return widget;
}
const BWidget* BWidget::root() const
{
	const BWidget* widget = this;
	while (widget->parent())
		widget = widget->parent();
	return widget;
}

void BWidget::setParent(BWidget* parent)
{
	if (member.parent != parent && parent != this)
	{
		BHolder<BWidget> holder;
		if (member.parent)
		{
			holder = this;
			member.parent->removeChild(this);
		}
		if (parent)
		{
			parent->addChild(this);
			holder = 0;
		}
	}
}
BWidget* BWidget::parent()
{
	return member.parent;
}
const BWidget* BWidget::parent() const
{
	return member.parent;
}

BWidget* BWidget::find(const BString& name)
{
	if (this->name() == name)
		return this;
	for (auto child : member.children)
	{
		BWidget* result = child->find(name);
		if (result)
			return result;
	}
	return 0;
}
bool BWidget::contain(const BWidget* widget)
{
	for (BWidgetHolderList::iterator it = member.children.begin(); it != member.children.end(); ++it)
	{
		if (*it == widget)
			return true;
	}
	return false;
}

void BWidget::addChild(BWidget* child)
{
	if (child && this != child && !member.children.contain(child))
	{
		member.children.append(child);
		if (widget_member(child)->parent)
			widget_member(child)->parent->removeChild(child);
		widget_member(child)->parent = this;
		if (widget_member(child)->window)
		{
			widget_member(child)->window->boss = 0;
			widget_member(child)->window->hideWindow();
			widget_member(child)->window = 0;
		}
		member.freshStyleTree(child);
	}
}
void BWidget::removeChild(BWidget* child)
{
	if (child && this != child && member.children.contain(child))
	{
		BLayout* layout = widget_member(child)->layout;
		if (layout && layout->host() == this)
		{
			layout->remove(child);
		}
		widget_member(child)->parent = 0;
		member.children.remove(child);
	}
}
void BWidget::clearChildren()
{
	if (member.children.size())
	{
		if (member.mainLayout)
			member.mainLayout->clear();
		if (member.leftLayout)
			member.leftLayout->clear();
		if (member.rightLayout)
			member.rightLayout->clear();
		if (member.topLayout)
			member.topLayout->clear();
		if (member.bottomLayout)
			member.bottomLayout->clear();

		for (int i = 0; i < member.children.size(); i++)
		{
			BWidget* child = member.children[i].ptr();
			widget_member(child)->parent = 0;
		}
		member.children.clear();
	}
}

int BWidget::childCount() const
{
	return member.children.size();
}
BWidget* BWidget::child(int index)
{
	return member.children(index).ptr();
}
const BWidget* BWidget::child(int index) const
{
	return member.children(index).ptr();
}

void BWidget::event(const BEvent& event)
{
	switch (event.type())
	{
	case Event_Show:
		this->showEvent(event);
		break;
	case Event_Hide:
		this->hideEvent(event);
		break;
	case Event_Change:
		this->changeEvent((const BChangeEvent&)event);
		break;
	case Event_Update:
		this->updateEvent((const BEvent&)event);
		break;
	case Event_Fresh:
		this->freshEvent((const BEvent&)event);
		break;
	case Event_KeyDown:
		this->keyDownEvent((const BKeyEvent&)event);
		break;
	case Event_KeyUp:
		this->keyUpEvent((const BKeyEvent&)event);
		break;
	case Event_Char:
		this->charEvent((const BCharEvent&)event);
		break;
	case Event_Paint:
		this->paintEvent(event);
		break;
	case Event_Move:
		this->moveEvent(event);
		break;
	case Event_Resize:
		this->resizeEvent(event);
		break;
	case Event_Adjust:
		this->adjustEvent(event);
		break;
	case Event_Focus:
		this->focusEvent((const BFocusEvent&)event);
		break;
	case Event_MouseEnter:
		this->mouseEnterEvent((const BMouseEvent&)event);
		break;
	case Event_MouseLeave:
		this->mouseLeaveEvent((const BMouseEvent&)event);
		break;
	case Event_MouseMove:
		this->mouseMoveEvent((const BMouseEvent&)event);
		break;
	case Event_MousePress:
		this->mousePressEvent((const BMouseEvent&)event);
		break;
	case Event_MouseRelease:
		this->mouseReleaseEvent((const BMouseEvent&)event);
		break;
	case Event_MouseWheel:
		this->mouseWheelEvent((const BMouseEvent&)event);
		break;
	case Event_MouseClick:
		this->mouseClickEvent((const BMouseEvent&)event);
		break;
	case Event_DoubleClick:
		this->mouseDoubleClickEvent((const BMouseEvent&)event);
		break;
	case Event_DragEnter:
		this->dragEnterEvent((const BDragEvent&)event);
		break;
	case Event_DragLeave:
		this->dragLeaveEvent((const BDragEvent&)event);
		break;
	case Event_DragMove:
		this->dragMoveEvent((const BDragEvent&)event);
		break;
	case Event_DragDrop:
		this->dragDropEvent((const BDragEvent&)event);
		break;
	default:
		break;
	}
}

void BWidget::showEvent(const BEvent& event)
{

}
void BWidget::hideEvent(const BEvent& event)
{

}

void BWidget::changeEvent(const BChangeEvent& changeEvent)
{

}
void BWidget::moveEvent(const BEvent& event)
{

}
void BWidget::resizeEvent(const BEvent& event)
{

}
void BWidget::adjustEvent(const BEvent& event)
{

}

void BWidget::updateEvent(const BEvent& event)
{

}
void BWidget::freshEvent(const BEvent& event)
{

}
void BWidget::paintEvent(const BEvent& event)
{
	BPainter painter(this);
	painter.drawBackground();
	painter.drawClient();
	painter.drawBorder();
	painter.drawPerch();
	painter.drawMargin();
}

void BWidget::focusEvent(const BFocusEvent& focusEvent)
{

}
void BWidget::keyDownEvent(const BKeyEvent& keyEvent)
{

}
void BWidget::keyUpEvent(const BKeyEvent& keyEvent)
{

}
void BWidget::charEvent(const BCharEvent& charEvent)
{

}

void BWidget::mouseEnterEvent(const BMouseEvent& mouseEvent)
{

}
void BWidget::mouseLeaveEvent(const BMouseEvent& mouseEvent)
{

}

void BWidget::mousePressEvent(const BMouseEvent& mouseEvent)
{

}
void BWidget::mouseReleaseEvent(const BMouseEvent& mouseEvent)
{

}
void BWidget::mouseMoveEvent(const BMouseEvent& mouseEvent)
{

}
void BWidget::mouseWheelEvent(const BMouseEvent& wheelEvent)
{

}

void BWidget::mouseClickEvent(const BMouseEvent& mouseEvent)
{
	emit(Signal_Clicked, mouseEvent.pos());
}
void BWidget::mouseDoubleClickEvent(const BMouseEvent& mouseEvent)
{
	emit(Signal_DoubleClicked, mouseEvent.pos());
}

void BWidget::dragEnterEvent(const BDragEvent& dragEvent)
{

}
void BWidget::dragLeaveEvent(const BDragEvent& dragEvent)
{

}
void BWidget::dragMoveEvent(const BDragEvent& dragEvent)
{

}
void BWidget::dragDropEvent(const BDragEvent& dragEvent)
{

}
